/* Anastasia Shuba
   Carolyn Ngo
   EECS22L
   01/14/12 
	Updates: 
	01/16/12 @ 11am - Nastia: fixed double precision on uneven division.
	01/17/12 @ 5:25 = Carolyn: Completed 1.2 Registers using an array. Moved your original operation for single value into my section for 
			  single operation for registers to avoid program conflict that I was experiencing. 
	01/18/12 @ 7:42pm - Carolyn: Fixed the bug with one operation on a single register or integer/float. Found a problem with single operations
			    on large numbers.
--------------------------------------------------------------
	ISSUES TO FIX: *after acc is promoted to double reading how do we know to make it go back to int reading?
			underflow, overflow - I believe I found a trick for this. Ceil(5.1689) = 6.0 and Ceil(5 or 5.0) = 5.0. 
			When Ceil(x) = x, we know that x equals its orginal self and thus  x has no floating point like .348947,
			this would only occur for numbers like, 5, 6.0, 7 or basically integer numbers so we keep make the number an integer. 
			When Ceil(x) != x, we know that the number is a floating point with decimal values. For ex, x = 5.12, Ceil(x) = 6. Since
			ceil(x) does not equal it's original value 5.12 we know that we should keep this as a double precision value????
			

			*When I add large numbers say + 120, the system errors with the wrong accumulator value. I do not know why that is happening.

			*valgrind leaks due to readline
			
*/

#include <stdio.h>
#include <stdlib.h>
#include <readline/readline.h>
#include <readline/history.h>
#include <string.h>

int manageHistory();

int main()
{
	char *cp;
	char sign[2];
	unsigned char DoubleOrInt;
	int numOfArg, num1, num2;
	double acc;
	numOfArg=num1=num2=0;
	acc=0;
	DoubleOrInt=0;
	cp=NULL;
	double RegisterArray[26] = {};
	int Argnum = 0;
	char letter[2], regsign[2];
	int regpos, regnum;
	manageHistory();

	while(1)
	{	
		if(DoubleOrInt==0) printf("%.0f", acc);
		else printf("%4.2f", acc);

		cp=readline(":");
		if(cp !=NULL) 
		{ 
			add_history(cp); 
			write_history("history.txt");
		}

		numOfArg=sscanf(cp, "%d %s %d", &num1, sign, &num2);
		printf("numOfArg is %d.\n", numOfArg);
		if(numOfArg == EOF) 
		{ 
			free(cp);
			break; 
		}

		Argnum = sscanf(cp,"%s %s %d", regsign, letter, &regnum);

		printf("Argnum is %d.\n", Argnum);
		if(Argnum == EOF)
		{
			free(cp);
			break;
		}

		/*Setting the Accumulator equal to the Register -Carolyn*/
		else if(Argnum == 1 && num1 == 0)
		{
			numOfArg =sscanf(cp,"%s", regsign);
			free(cp);
			if(strcmp(regsign,"A") == 0 || strcmp(regsign,"a") == 0)
			{
			acc = RegisterArray[0];
			}
			
			if(strcmp(regsign,"B") == 0 || strcmp(regsign,"b") == 0)
			{
			acc = RegisterArray[1];
			}
			
			if(strcmp(regsign,"C") == 0 || strcmp(regsign,"c") == 0)
			{
			acc = RegisterArray[2];
			}
			
			if(strcmp(regsign,"D") == 0 || strcmp(regsign,"d") == 0)
			{
			acc = RegisterArray[3];
			}
			
			if(strcmp(regsign,"E") == 0 || strcmp(regsign,"e")  == 0)
			{
			acc = RegisterArray[4];
			}
			
			if(strcmp(regsign,"F") == 0 || strcmp(regsign, "f") == 0)
			{
			acc = RegisterArray[5];
			}
			
			if(strcmp(regsign,"G") == 0 || strcmp(regsign, "g") == 0)
			{
			acc = RegisterArray[6];
			}
			
			if(strcmp(regsign,"H") == 0 || strcmp(regsign, "h") == 0)
			{
			acc = RegisterArray[7];
			}
			
			if(strcmp(regsign, "I") == 0 || strcmp(regsign, "i") == 0)
			{
			acc = RegisterArray[8];
			}
			
			if(strcmp(regsign,"J") == 0 || strcmp(regsign, "j") == 0)
			{
			acc = RegisterArray[9];
			}
			
			if(strcmp(regsign,"K") == 0 || strcmp(regsign,"k") == 0)
			{
			acc = RegisterArray[10];
			}
			
			if(strcmp(regsign, "L") == 0 || strcmp(regsign,"l") == 0)
			{
			acc = RegisterArray[11];
			}
		
			if(strcmp(regsign, "M") == 0 || strcmp(regsign,"m")== 0)
			{
			acc = RegisterArray[12];
			}

			if(strcmp(regsign, "N") == 0 || strcmp(regsign,"n") == 0)
			{
			acc = RegisterArray[13];
			}

			if(strcmp(regsign,"O") == 0 || strcmp(regsign, "o") == 0)
			{
			acc = RegisterArray[14];
			}

			if(strcmp(regsign,"P") == 0 || strcmp(regsign,"p") == 0)
			{
			acc = RegisterArray[15];
			}

			if(strcmp(regsign,"Q") == 0 || strcmp(regsign,"q") == 0)
			{
			acc = RegisterArray[16];
			}

			if(strcmp(regsign,"R") == 0 || strcmp(regsign,"r") == 0)
			{
			acc = RegisterArray[17];
			}
			
			if(strcmp(regsign,"S") == 0 || strcmp(regsign,"s") == 0)
			{
			acc = RegisterArray[18];
			}

			if(strcmp(regsign,"T") == 0 || strcmp(regsign,"t") == 0)
			{
			acc = RegisterArray[19];
			}
		
			if(strcmp(regsign,"U") == 0 || strcmp(regsign,"u") == 0)
			{
			acc = RegisterArray[20];
			}
		
			if(strcmp(regsign,"V") == 0 || strcmp(regsign,"v") == 0)
			{
			acc = RegisterArray[21];
			}
			
			if(strcmp(regsign,"W") == 0 || strcmp(regsign,"w") == 0)
			{
			acc = RegisterArray[22];
			}
		
			if(strcmp(regsign,"X") == 0 || strcmp(regsign, "w") == 0)
			{
			acc = RegisterArray[23];
			}
		
			if(strcmp(regsign,"Y") == 0 || strcmp(regsign,"y") ==0)
			{
			acc = RegisterArray[24];
			}
		
			if(strcmp(regsign,"Z") == 0 || strcmp(regsign,"z") == 0)
			{
			acc = RegisterArray[25];
			}
		}

		/*For register operators, for example "+ X" -Carolyn, added one of your sections here*/
		else if(Argnum == 2 && regnum == 0 && num1 == 0)
		{
		Argnum = sscanf(cp,"%s %s", regsign, letter);

		free(cp);

			if(strcmp(letter,"A") == 0 || strcmp(letter,"a") == 0)
			{
			regpos = 0;
			}
			else if(strcmp(letter,"B") == 0 || strcmp(letter,"b") == 0)
			{
			regpos = 1;
			}
			else if(strcmp(letter,"C") == 0 || strcmp(letter,"c") ==0)
			{
			regpos = 2;
			}
			else if(strcmp(letter,"D") == 0 || strcmp(letter,"d") == 0)
			{
			regpos = 3;
			}
			else if(strcmp(letter,"E") == 0 || strcmp(letter,"e") == 0)
			{
			regpos = 4;
			}
			else if(strcmp(letter,"F") == 0 || strcmp(letter,"f") == 0)
			{
			regpos = 5;
			}
			else if(strcmp(letter,"G") ==0 || strcmp(letter,"g") == 0)
			{
			regpos = 6;
			}
			else if(strcmp(letter,"H") == 0 || strcmp(letter,"h") == 0)
			{
			regpos = 7;
			}
			else if(strcmp(letter,"I") == 0 || strcmp(letter,"i") == 0)
			{
			regpos = 8;
			}
			else if(strcmp(letter,"J") == 0 || strcmp(letter,"j") == 0)
			{
			regpos = 9;
			}
			else if(strcmp(letter,"K") == 0 || strcmp(letter,"k") == 0)
			{
			regpos = 10;
			}
			else if(strcmp(letter,"L") == 0 || strcmp(letter,"l") == 0)
			{
			regpos = 11;
			}
			else if(strcmp(letter,"M") == 0 || strcmp(letter,"m") == 0)
			{
			regpos = 12;
			}
			else if(strcmp(letter,"N") == 0 || strcmp(letter,"n") == 0)
			{
			regpos = 13;
			}
			else if(strcmp(letter,"P") == 0 || strcmp(letter,"p") == 0)
			{
			regpos = 14;
			}
			else if(strcmp(letter,"O") == 0 || strcmp(letter,"o") == 0)
			{
			regpos = 15;
			}
			else if(strcmp(letter,"Q") == 0 || strcmp(letter,"q") == 0)
			{
			regpos = 16;
			}
			else if(strcmp(letter,"R") == 0 || strcmp(letter,"r") == 0)
			{
			regpos = 17;
			}
			else if(strcmp(letter,"S") == 0 || strcmp(letter,"s") == 0)
			{
			regpos = 18;
			}
			else if(strcmp(letter,"T") == 0 || strcmp(letter,"t") == 0)
			{
			regpos = 19;
			}
			else if(strcmp(letter,"U") == 0 || strcmp(letter,"u") == 0)
			{
			regpos = 20;
			}
			else if(strcmp(letter,"V") == 0 || strcmp(letter,"v") == 0)
			{
			regpos = 21;
			}
			else if(strcmp(letter,"W") == 0 || strcmp(letter,"w") == 0)
			{
			regpos = 22;
			}
			else if(strcmp(letter,"X") == 0 || strcmp(letter,"x") == 0)
			{
			regpos = 23;
			}
			else if(strcmp(letter,"Y") == 0 || strcmp(letter,"y") == 0)
			{
			regpos = 24;
			}
			else if(strcmp(letter,"Z") == 0 || strcmp(letter,"z") == 0)
			{
			regpos = 25;
			}

			if(strcmp(regsign,"+") == 0)
			{
			acc = acc + RegisterArray[regpos];
			}
			else if(strcmp(regsign,"-") == 0)
			{
			acc = acc - RegisterArray[regpos];
			}
			else if (strcmp(regsign,"*") == 0)
			{
			acc = acc * RegisterArray[regpos];
			}
			else if (strcmp(regsign,"/") == 0)
			{
			acc = acc / RegisterArray[regpos];
			}
			else if(strcmp(regsign,"@") == 0)
			{
			RegisterArray[regpos] = acc;
			}

		}
		
		/*Setting a register equal to a value e.x. X = 3 -Carolyn*/
		else if(Argnum == 3 && num1 == 0)
		{
		Argnum = sscanf(cp,"%s %s %d",letter, regsign, &regnum);
		free(cp);
			if(strcmp(letter,"A") == 0 || strcmp(letter,"a") == 0)
			{
			regpos = 0;
			}
			else if(strcmp(letter,"B") == 0 || strcmp(letter,"b") == 0)
			{
			regpos = 1;
			}
			else if(strcmp(letter,"C") == 0 || strcmp(letter,"c") == 0)
			{
			regpos = 2;
			}
			else if(strcmp(letter,"D") == 0 || strcmp(letter,"d") == 0)
			{
			regpos = 3;
			}
			else if(strcmp(letter,"E") == 0 || strcmp(letter,"e") == 0)
			{
			regpos = 4;
			}	
			else if(strcmp(letter,"F") == 0 || strcmp(letter,"f") == 0)
			{
			regpos = 5;
			}
			else if(strcmp(letter,"G") == 0 || strcmp(letter,"g") == 0)
			{
			regpos = 6;
			}
			else if(strcmp(letter,"H") == 0 || strcmp(letter,"h") == 0)
			{
			regpos = 7;
			}
			else if(strcmp(letter,"I") == 0 || strcmp(letter,"i") == 0)
			{
			regpos = 8;
			}
			else if(strcmp(letter,"J") == 0 || strcmp(letter,"j") == 0)
			{
			regpos = 9;
			}
			else if(strcmp(letter,"K") == 0 || strcmp(letter,"j") == 0)
			{
			regpos= 10;
			}
			else if(strcmp(letter,"L") == 0 || strcmp(letter,"l") == 0)
			{
			regpos = 11;
			}
			else if(strcmp(letter,"M") == 0 || strcmp(letter,"m") == 0)
			{	
			regpos = 12;
			}
			else if(strcmp(letter,"N") == 0 || strcmp(letter,"n") == 0)
			{
			regpos = 13;
			}
			else if(strcmp(letter,"O") == 0 || strcmp(letter,"o") == 0)
			{
			regpos = 14;
			}
			else if(strcmp(letter,"P") == 0 || strcmp(letter,"p") == 0)
			{		
			regpos = 15;
			}
			else if(strcmp(letter,"Q") == 0 || strcmp(letter,"q") == 0 )
			{
			regpos = 16;
			}
			else if(strcmp(letter,"R") == 0 || strcmp(letter,"r") == 0)
			{
			regpos = 17;
			}
			else if(strcmp(letter,"S") == 0 || strcmp(letter,"s") == 0)
			{
			regpos = 18;
			}
			else if(strcmp(letter,"T") == 0 || strcmp(letter,"t") == 0)
			{
			regpos = 19;
			}
			else if(strcmp(letter,"U") == 0 || strcmp(letter,"u") == 0 )
			{
			regpos = 20;
			}
			else if(strcmp(letter,"V") == 0 || strcmp(letter,"v") == 0)
			{
			regpos = 21;
			}
			else if(strcmp(letter,"W") == 0 || strcmp(letter,"w") == 0)
			{
			regpos = 22;
			}
			else if(strcmp(letter,"X") == 0 || strcmp(letter,"x") == 0)
			{
			regpos = 23;
			}
			else if(strcmp(letter,"Y") == 0 || strcmp(letter,"y") == 0)
			{
			regpos = 24;
			}
			else if(strcmp(letter,"Z") == 0 || strcmp(letter,"z") == 0 )
			{
			regpos = 25;
			}
			
			if(strcmp(regsign,"=") == 0)
			{
			RegisterArray[regpos] = regnum;
			} 
		}

			/*For ops with one integer value*/

			else if(num1 == 0 && numOfArg < 3 && sign != 0)
			{
			numOfArg=sscanf(cp, "%s %d", sign, &num2);
	
		 		if(strlen(sign) > 1) printf("Invalid input!\n");
				else if(strcmp(sign, "+") == 0)
				{
				acc=acc+num2;
				}
				else if(strcmp(sign, "-") == 0)
				{
				acc=acc-num2;
				}
				else if(strcmp(sign, "*") == 0)
				{
				acc=acc*num2;
				}
				else if(strcmp(sign, "/") == 0)
				{	
					if(num2==0) printf("Error: cannot divide by zero.\n");
					else if((int)acc%num2 != 0)
					{
						 DoubleOrInt=1;
 					 	 acc=(double)(acc/num2);
					}
					else acc=acc/num2;
				}
				free(cp);
			}


		/*protection against input like "2 +3"*/
		else if(num2==0 && numOfArg == 2)
		{
			printf("Invalid input. Please enter spaces between binary operators and numbers.\n");
		}
		
		/* Positive/Negative numbers being entered */
		else if(num2==0 && numOfArg == 1)
		{
			numOfArg=sscanf(cp, "%d", &num2);
			free(cp);
			acc=num2;
		}

		/* For ops with 2 numbers*/
		else if(numOfArg == 3)
		{
			if(strcmp(sign, "+") == 0)
			{
				acc=num1+num2;
			}

			else if(strcmp(sign, "-") == 0)
			{
				acc=num1-num2;
			}

			else if(strcmp(sign, "*") == 0)
			{
				acc=num1*num2;
			}

			else if(strcmp(sign, "/") == 0)
			{
				if(num2==0) printf("Error: cannot divide by zero.\n");
				else if(num1%num2 != 0)
				{
					 DoubleOrInt=1;
					 acc= (double) num1/num2;
				}
				else acc=num1/num2;
			}
		}

		else 
		{
			printf("Invalid input!\n");
		}
		/*for the next loop*/
		num1=num2=numOfArg=regnum=0;
		sign[0]=0;
		letter[0]=0;
		
	}
	return 0;
}


int manageHistory()
{
	FILE *History;
	int x;
	History = fopen("history.txt", "r");

	if( History == 0 ) 
	{
		printf("Could not open history of commands.\n");
		return 1;
	}
	
	else if(fgetc(History) == EOF) return 0;
	
	else
	{
		x=read_history("history.txt");
		if(x !=0 )
		{
			 printf("Error while reading history file.\n");
			return 2;
		}
		else return 0;
	}
}






























	
